package com.dkha.server.services.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dkha.common.enums.ApiUrlEnum;
import com.dkha.common.enums.YNEnums;
import com.dkha.common.exception.DkException;
import com.dkha.common.fileupload.MinioUtil;
import com.dkha.common.http.HttpUtil;
import com.dkha.common.modules.vo.ApiVO;
import com.dkha.common.modules.vo.ReturnVO;
import com.dkha.common.modules.vo.face.*;
import com.dkha.common.modules.vo.search.SearchPortraitVo;
import com.dkha.common.modules.vo.search.SearchRequestVo;
import com.dkha.common.modules.vo.search.SearchResultVo;
import com.dkha.common.page.PageParam;
import com.dkha.common.systemcode.SystemCode;
import com.dkha.common.util.DateUtils;
import com.dkha.common.util.IdCardUtil;
import com.dkha.common.util.JsonUtil;
import com.dkha.common.util.UtilValidate;
import com.dkha.server.modules.entities.Portrait;
import com.dkha.server.mappers.PortraitMapper;
import com.dkha.server.services.IPortraitService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.*;

/**
 * <p>
 * 人像表 服务实现类
 * </p>
 *
 * @author Spring
 * @since 2019-12-09
 */
@Service
public class PortraitServiceImpl extends ServiceImpl<PortraitMapper, Portrait> implements IPortraitService {
    @Autowired
    private MinioUtil minioUtil;

    @Resource
    private PortraitMapper portraitMapper;
    @Value("${api.server.prefix}")
    private String link;
    @Resource
    private HttpUtil httpUtil;
    @Autowired
    private Gson gson;
    @Value("${api.server.prefix}")
    private String apiRequestPrefix;
    @Value("${api.max.result}")
    private String apiMaxResult;
    @Value("${minio.bucketName}")
    private String bucketName;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Portrait addPortrait(String libraryId, MultipartFile multipartFile) {
        /**保存数据*/
        Portrait portrait;
        String filename;
        String multipartFileName = multipartFile.getOriginalFilename();
        if (UtilValidate.isNotEmpty(multipartFileName)) {
            filename = multipartFileName.substring(0, multipartFileName.lastIndexOf("."));
        } else {
            throw new DkException(SystemCode.FILE_ERROR.code, multipartFileName + "文件名格式不正确");
        }
        ImagesVO imageVO = new ImagesVO();
        setimageVO(imageVO, filename);
        try {
            String name = imageVO.getName();
            int hash = name.hashCode();
            if (hash < 0) {
                hash = 0 - hash;
            }
            JSONObject map = minioUtil.uploadFiles(multipartFile.getInputStream(), String.valueOf(hash % 500), multipartFile.getOriginalFilename(), null);
            map.get("url");
            imageVO.setNation("");
            imageVO.setUrl(map.get("url").toString());
            imageVO.setLibraryId(libraryId);
        } catch (Exception e) {
            throw new DkException(multipartFileName + "文件上传失败");
        }
        //imagesVO.setFaces(faces);
        /**调用微云新增人像*/
        ApiVO face = (ApiVO) httpUtil.post(link + ApiUrlEnum.FACE_POSTURL.getUrl(), imageVO, ApiVO.class);
        String json = gson.toJson(face.getData());
        if (UtilValidate.isNotEmpty(face) && face.getCode().equals(200)) {
            portrait = save(null, imageVO);
        } else {
            throw new DkException(SystemCode.FACESRH_ERROR.code, face.getMessage());
        }
        return portrait;
    }

    @Override
    public List<ApiSearchFaceRectVO> pictureDetection(MultipartFile multipartFile) throws Exception {
        //人脸检测url
        String faceSearchUrl = apiRequestPrefix + ApiUrlEnum.FACE_SEARCH.getUrl();
        //组织返回结果集
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        int hash = uuid.hashCode();
        if (hash < 0) {
            hash = 0 - hash;
        }
        JSONObject map;
        try {
            map = minioUtil.uploadFiles(multipartFile.getInputStream(), String.valueOf(hash % 500), uuid, null);
        } catch (Exception e) {
            throw new DkException(multipartFile.getOriginalFilename() + "文件上传失败");
        }
        //组装api请求数据
        ReturnVO returnVO = (ReturnVO) httpUtil.post(faceSearchUrl + "?url=" + map.getString("url"), null, ReturnVO.class);
        if (returnVO.getCode() != 200) {
            throw new DkException(returnVO.getMessage());
        }
        //反序列化
        List<ApiSearchFaceRectVO> apiSearchFaceRectVOList = JsonUtil.string2Obj(JsonUtil.obj2String(returnVO.getData()), new TypeReference<List<ApiSearchFaceRectVO>>() {
        });
        if (UtilValidate.isEmpty(apiSearchFaceRectVOList)) {
            try {
                minioUtil.removeObject(bucketName, map.getString("url"));
            } catch (Exception e) {
                throw new DkException("删除人脸失败");
            }
            throw new DkException("当前上传中未检测到人脸,请重新上传");
        }

        return apiSearchFaceRectVOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Portrait addPortraitPng(String libraryId, MultipartFile multipartFile) {
        /**保存数据*/
        Portrait portrait;
        String multipartFileName = multipartFile.getOriginalFilename();
        ImagesVO imageVO = new ImagesVO();
        try {
            JSONObject map = minioUtil.uploadFile(multipartFile.getInputStream(), multipartFile.getOriginalFilename(), null);
            imageVO.setNation("");
            imageVO.setUrl(map.get("url").toString());
            imageVO.setLibraryId(libraryId);
        } catch (Exception e) {
            throw new DkException(multipartFileName + "文件上传失败");
        }
        //setimageVO(imageVO, s);
        //imagesVO.setFaces(faces);
        /**调用微云新增人像*/
        ApiVO face = (ApiVO) httpUtil.post(link + ApiUrlEnum.FACE_POSTURL.getUrl(), imageVO, ApiVO.class);
        String json = gson.toJson(face.getData());
        ImageReturnVO imageReturnVO = null;
        if (UtilValidate.isNotEmpty(json)) {
            imageReturnVO = gson.fromJson(json, ImageReturnVO.class);
        }
        if (UtilValidate.isNotEmpty(imageReturnVO)) {
            portrait = save(imageReturnVO, imageVO);
        } else {
            throw new DkException(SystemCode.FACESRH_ERROR.code, face.getMessage());
        }
        return portrait;
    }

    @Override
    public Portrait addPortraitPngs(String libraryId, String multipartFile) {
        /**保存数据*/
        Portrait portrait;
        ImagesVO imageVO = new ImagesVO();
        imageVO.setNation("");
        imageVO.setUrl(multipartFile);
        imageVO.setLibraryId(libraryId);
        /**调用微云新增人像*/
        ApiVO face = (ApiVO) httpUtil.post(link + ApiUrlEnum.FACE_POSTURL.getUrl(), imageVO, ApiVO.class);
        String json = gson.toJson(face.getData());
        ImageReturnVO imageReturnVO = null;
        if (UtilValidate.isNotEmpty(json)) {
            imageReturnVO = gson.fromJson(json, ImageReturnVO.class);
        }
        if (UtilValidate.isNotEmpty(imageReturnVO)) {
            portrait = save(imageReturnVO, imageVO);
        } else {
            throw new DkException(SystemCode.FACESRH_ERROR.code, face.getMessage());
        }
        return portrait;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Portrait> addPortraits(String libraryId, MultipartFile[] files) {
        List<Portrait> list = new ArrayList<>();
        try {
            //判断file数组不能为空并且长度大于0
            if (files != null && files.length > 0) {
                for (int i = 0; i < files.length; i++) {
                    JSONObject map = minioUtil.uploadFile(files[i].getInputStream(), files[i].getOriginalFilename(), null);
                    map.get("path");
                    String[] message = new String[4];
                    String multipartFileName = files[i].getOriginalFilename();
                    if (UtilValidate.isNotEmpty(multipartFileName)) {
                        String filename = multipartFileName.substring(0, multipartFileName.lastIndexOf("."));
                        message = filename.split("_");
                    }
                    /**文件名：身份证_姓名*/
                    ImagesVO imageVO = new ImagesVO();
//                    setimageVO(imageVO, message);
                    imageVO.setUrl(map.get("url").toString());
                    List<ImageVO> faces = new ArrayList<>();
                    //faces.add(imageVO);
                    imageVO.setLibraryId(libraryId);
                    //imagesVO.setFaces(faces);
                    /**调用微云新增人像*/
                    ApiVO face = (ApiVO) httpUtil.post(link + ApiUrlEnum.FACE_POSTURL.getUrl(), imageVO, ApiVO.class);
                    String json = gson.toJson(face.getData());
                    ImageReturnVO imageReturnVO = null;
                    if (UtilValidate.isNotEmpty(json)) {
                        imageReturnVO = gson.fromJson(json, ImageReturnVO.class);
                    }
                    if (UtilValidate.isNotEmpty(imageReturnVO)) {
                        Portrait portrait = save(imageReturnVO, imageVO);
                        list.add(portrait);
                    } else {
                        throw new DkException(face.getMessage());
                    }
                }
            }
            return list;
            /**调用微云新增人像*/
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public Portrait updatePortrait(Portrait portrait) {
        try {
            if (UtilValidate.isNotEmpty(portrait)) {
                ImagesVO imageVO = new ImagesVO();
                setSex(imageVO, portrait.getIdCard());
                portrait.setSex(imageVO.getGender());
                java.sql.Date birthDate = getBirthDate(portrait.getIdCard());
                portrait.setBirthDate(birthDate);
                portrait.setAge(DateUtils.getAge(portrait.getBirthDate()));
            }
            portraitMapper.updateById(portrait);
        } catch (Exception e) {
            throw new DkException("修改人像失败");
        }
        return portrait;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long deletePortrait(Long idPortrait) {
        try {
            Portrait portrait = new Portrait();
            portrait.setIdPortrait(idPortrait);
            Portrait portrait1 = portraitMapper.queryPortrait(idPortrait);
            /**调用API*/
            if (UtilValidate.isNotEmpty(portrait1)) {
                /**调用微云删除人像*/
                ApiVO face = (ApiVO) httpUtil.delete(link + ApiUrlEnum.FACE_POSTURL.getUrl() + "/" + portrait1.getIdFactory() + "/" + idPortrait, ApiVO.class);

                if (UtilValidate.isNotEmpty(face) && face.getCode().equals(200)) {
                    minioUtil.removeObject(bucketName, portrait1.getUrl());
                } else {
                    log.error("wy删除失败");
                }
                int i = portraitMapper.deleteById(portrait);
            }
        } catch (Exception e) {
            throw new DkException("删除人像失败");
        }
        return idPortrait;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> deletePortraits(List<Long> idPortrait) {
        try {
            if (UtilValidate.isNotEmpty(idPortrait)) {
                for (int i = 0; i < idPortrait.size(); i++) {
                    Portrait portrait1 = portraitMapper.queryPortrait(idPortrait.get(i));
                    if (UtilValidate.isEmpty(portrait1)) {
                        continue;
                    }
                    /**调用微云删除人像*/
                    ApiVO face = (ApiVO) httpUtil.delete(link + ApiUrlEnum.FACE_POSTURL.getUrl() + "/" + portrait1.getIdFactory() + "/" + portrait1.getIdPortrait(), ApiVO.class);
                    if (face.getMessage().equals("成功")) {
                        minioUtil.removeObject(bucketName, portrait1.getUrl());
                    } else {
                        log.error("wy删除失败");
                    }
                    portraitMapper.deleteById(idPortrait.get(i));
                }
            }
        } catch (Exception e) {
            throw new DkException("删除人像失败");
        }
        return idPortrait;
    }

    @Override
    //public ReturnVO queryPortrait(PageParam pageParam) {
    public Page<Portrait> queryPortrait(PageParam pageParam) {
       /* PagePortraitVO pagePortraitVO = new PagePortraitVO();
        pagePortraitVO.setLibraryId(pageParam.getNote().get("libraryId"));
        PageVO pageVO = new PageVO();
        pageVO.setPageNo(pageParam.getPageNo());
        pageVO.setPageSize(pageParam.getPageSize());
        pagePortraitVO.setPage(pageVO);
        ReturnVO faceLibrary1 = (ReturnVO) httpUtil.post(link+ ApiUrlEnum.FACELIBS_POSTURL.getUrl(), pagePortraitVO, ReturnVO.class);*/
        /**创建page对象*/
        Page<Portrait> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
        /**设置模糊查询参数*/
        Map<String, String> paramsNote = pageParam.getNote();

        /**分页查询*/
        //List<Portrait> postList = portraitMapper.selectPage(page, paramsNote.get("factoryName"));
        List<Portrait> postList = portraitMapper.queryPage(page, paramsNote);
        if (UtilValidate.isNotEmpty(postList)) {
            for (Portrait portrait : postList) {
                /**年龄*/
                if (UtilValidate.isNotEmpty(portrait.getBirthDate())) {
                    portrait.setAge(DateUtils.getAge(portrait.getBirthDate()));
                }
            }
        }
        page.setRecords(postList);
        return page;

        //  return faceLibrary1;
    }

    /**
     * 获取出生年月
     *
     * @param idCard
     * @return
     */
    public java.sql.Date getBirthDate(String idCard) {
        if (null != idCard && !idCard.equals("") && idCard.length() == 18) {
            LocalDate date = LocalDate.of(Integer.parseInt(idCard.substring(6, 10)), Integer.parseInt(idCard.substring(10, 12)), Integer.parseInt(idCard.substring(12, 14)));
            try {
                ZonedDateTime zonedDateTime = date.atStartOfDay(ZoneId.systemDefault());
                return new java.sql.Date(Date.from(zonedDateTime.toInstant()).getTime());
            } catch (Exception e) {
                throw new DkException("身份信息有误");
            }
        }
        return null;
    }

    /**
     * 保存数据
     *
     * @return
     */
    public Portrait save(ImageReturnVO imageReturnVO, ImagesVO imageVO) {
        Portrait portrait = new Portrait();
        portrait.setIdPortrait(Long.parseLong(imageVO.getFaceId()));
        portrait.setFeatId(imageVO.getFaceId());
        portrait.setFaceIds(imageVO.getFaceId());
        portrait.setName(imageVO.getName());
        portrait.setIdFactory(Long.parseLong(imageVO.getLibraryId()));
        portrait.setUrl(imageVO.getUrl());
        portrait.setBackgroundUrl(imageVO.getUrl());

//        if (UtilValidate.isNotEmpty(imageReturnVO.getFace())) {
//            /**背景地址*/
//            if (UtilValidate.isNotEmpty(imageReturnVO.getFace().getUrl())) {
//                portrait.setBackgroundUrl(imageReturnVO.getFace().getUrl());
//            }
//            /**人脸地址*/
//            if (UtilValidate.isNotEmpty(imageReturnVO.getFace().getFaceUrl())) {
//                portrait.setUrl(imageReturnVO.getFace().getFaceUrl());
//            }
//        }

//        if (UtilValidate.isNotEmpty(imageReturnVO.getLibraryId())) {
//            portrait.setIdFactory(Long.parseLong(imageVO.getLibraryId()));
//        }
        /**出生年月*/
//        if (UtilValidate.isNotEmpty(imageVO.getIdCard())) {
//            portrait.setBirthDate(getBirthDate(imageVO.getIdCard()));
//        }
//        /**身份证信息*/
//        if (UtilValidate.isNotEmpty(imageReturnVO.getFace().getIdCard())) {
//            portrait.setIdCard(imageReturnVO.getFace().getIdCard());
//        }
//        if (UtilValidate.isNotEmpty(imageVO.getName())) {
//
//        }
//        if (UtilValidate.isNotEmpty(imageReturnVO.getFaceId())) {
//            portrait.setFaceIds(imageReturnVO.getFaceId());
//        }
//        if (UtilValidate.isNotEmpty(imageVO.getGender())) {
//            portrait.setSex(imageVO.getGender());
//        }
        portrait.setIsValid(YNEnums.YES.code);
        portrait.setCreateTime(new Date());
        portrait.setUpdateTime(new Date());
        try {
            int insert = portraitMapper.insert(portrait);
        } catch (Exception e) {
            throw new DkException("保存人像信息错误");
        }
        return portrait;
    }

    /**
     * 设置性别
     *
     * @param imageVO
     * @param idCard
     */
    public void setSex(ImagesVO imageVO, String idCard) {
        if (UtilValidate.isNotEmpty(idCard)) {
            if (idCard.length() == 15) {
                String sex = idCard.substring(13, 14); //取指定位置的值(16位之后,17位结束;)
                int b = Integer.parseInt(sex);//强制类型转换
                if (b % 2 == 0) {
                    imageVO.setGender("1");//女
                } else {
                    imageVO.setGender("0");
                }
            }
            if (idCard.length() == 18) {
                String sex = idCard.substring(16, 17); //取指定位置的值(16位之后,17位结束;)
                int b = Integer.parseInt(sex);//强制类型转换
                if (b % 2 == 0) {
                    imageVO.setGender("1");//女
                } else {
                    imageVO.setGender("0");
                }
            }
            imageVO.setIdCard(idCard);
        }
    }

    private void setimageVO(ImagesVO imageVO, String filename) {
        imageVO.setFaceId(String.valueOf(System.currentTimeMillis()));
        imageVO.setName(filename);
    }

//    public void setimageVO(ImagesVO imageVO, String[] identityMessage) {
//        if (identityMessage.length > 0) {
//            /**文件名：身份证_姓名_性别*/
//            if (!IdCardUtil.isValidatedAllIdcard(identityMessage[0])) {
//                throw new DkException(SystemCode.IDCARD_ERROR.code, "身份证号码输入不正确");
//            }
//            if (UtilValidate.isNotEmpty(identityMessage[0])) {
//                setSex(imageVO, identityMessage[0]);
//                imageVO.setIdCard(identityMessage[0]);
//            }
//            if (UtilValidate.isNotEmpty(identityMessage[1])) {
//                imageVO.setName(identityMessage[1]);
//            }
//        }
//    }

    @Override
    public SearchResultVo libSearchPage(SearchRequestVo searchRequestVo) {
        //用户传输图片过来进行检索，调用人脸API
        if (UtilValidate.isNotEmpty(searchRequestVo.getFaceImageRequestList())) {
            return this.libSearPageByApi(searchRequestVo);
        } else {
            //调用数据库查询接口进行查询，不涉及人脸检索
            Page<SearchPortraitVo> searchPage = this.findSearchPage(searchRequestVo.getPageParam(), null, searchRequestVo.getLibIdList(), null);
            SearchResultVo searchResultVo = new SearchResultVo();
            searchResultVo.setResultPage(searchPage);
            //将部分请求参数返回前端，方便前端进行数据绑定
            searchResultVo.setRequestLibIdList(searchRequestVo.getLibIdList());
            if (UtilValidate.isNotEmpty(searchRequestVo.getPageParam().getNote().get("search"))) {
                searchResultVo.setRequestSearch(searchRequestVo.getPageParam().getNote().get("search").replaceAll("%", ""));
            }
            return searchResultVo;
        }
    }

    /**
     * 人脸检索--api调用渠道
     *
     * @param searchRequestVo
     * @return
     */
    private SearchResultVo libSearPageByApi(SearchRequestVo searchRequestVo) {
        String requestUrl = apiRequestPrefix + ApiUrlEnum.FACE_SEARCH_LIB.getUrl();
        /**
         * 返回结果集
         */
        SearchResultVo searchResultVo = new SearchResultVo();
        /**
         * 图片搜索，如果当前为第一页，则调用sdk查询，反之利用第一页sdk返回的数据
         * 进行操作
         */
        if (searchRequestVo.getPageParam().getPageNo() == 1) {
            //人脸ID,分数集合,及其对应分数--由sdk返回
            Map<String, Double> faceApiResultMap = new LinkedHashMap<>();
            for (String faceImage : searchRequestVo.getFaceImageRequestList()) {
                /**
                 * 构建请求对象
                 */
                ApiFaceSearchVO apiFaceSearchVO = new ApiFaceSearchVO();
                //设置图片url
                apiFaceSearchVO.setUrl(faceImage);
                //设置检索库
                apiFaceSearchVO.setLibraryIds(searchRequestVo.getLibIdList());
                //设置阀值
                if (UtilValidate.isNotEmpty(searchRequestVo.getMinScore())) {
                    apiFaceSearchVO.setMinScore(Double.parseDouble(searchRequestVo.getMinScore()));
                }
                //设置分页
                PageVO pageVO = new PageVO();
                pageVO.setPageSize(Integer.parseInt(apiMaxResult));
                apiFaceSearchVO.setPageVO(pageVO);
                //获取解析结果
                ReturnVO returnVO = (ReturnVO) httpUtil.post(requestUrl, apiFaceSearchVO, ReturnVO.class);
                if (returnVO.getCode() != 200) {
                    throw new DkException(returnVO.getMessage());
                }
                //解析结果
                ApiFaceSearchReturnVO apiFaceSearchReturnVO = JsonUtil.string2Obj(JsonUtil.obj2String(returnVO.getData()), new TypeReference<ApiFaceSearchReturnVO>() {
                });
                if (UtilValidate.isNotEmpty(apiFaceSearchReturnVO)) {
                    for (ApiFaceSearchFacesVO apiFaceSearchFacesVO : apiFaceSearchReturnVO.getFaces()) {
                        List<ApiFaceSearchFaceVO> faceList = apiFaceSearchFacesVO.getFaceList();
                        if (UtilValidate.isNotEmpty(faceList)) {
                            for (ApiFaceSearchFaceVO apiFaceSearchFaceVO : faceList) {
                                faceApiResultMap.put(apiFaceSearchFaceVO.getFaceId(), apiFaceSearchFaceVO.getHitSimilarity());
                            }
                        }
                    }
                }
                if (UtilValidate.isEmpty(faceApiResultMap)) {
                    /**
                     * 为空的时候组织数据，便于前端组织数据
                     */
                    Page<SearchPortraitVo> page = new Page<>();
                    searchResultVo.setResultPage(page);
                    searchResultVo.setFaceImageRequestList(new ArrayList<>());
                    searchResultVo.setFaceApiResultMap(new HashMap<>());
                    //将部分请求参数返回前端，方便前端进行数据绑定
                    searchResultVo.setRequestLibIdList(searchRequestVo.getLibIdList());
                    if (UtilValidate.isNotEmpty(searchRequestVo.getPageParam().getNote().get("search"))) {
                        searchResultVo.setRequestSearch(searchRequestVo.getPageParam().getNote().get("search").replaceAll("%", ""));
                    }
                    return searchResultVo;
                } else {
                    // 对API调用返回的数据进行排序
                    faceApiResultMap = this.sort(faceApiResultMap);
                }
            }
            //获取分页数据
            Page<SearchPortraitVo> searchPage = this.findSearchPage(searchRequestVo.getPageParam(), new ArrayList<>(faceApiResultMap.keySet()), searchRequestVo.getLibIdList(), faceApiResultMap);
            searchResultVo.setResultPage(searchPage);
            searchResultVo.setFaceApiResultMap(faceApiResultMap);
            searchResultVo.setFaceImageRequestList(searchRequestVo.getFaceImageRequestList());
            //将部分请求参数返回前端，方便前端进行数据绑定
            searchResultVo.setRequestLibIdList(searchRequestVo.getLibIdList());
            if (UtilValidate.isNotEmpty(searchRequestVo.getPageParam().getNote().get("search"))) {
                searchResultVo.setRequestSearch(searchRequestVo.getPageParam().getNote().get("search").replaceAll("%", ""));
            }
            return searchResultVo;
        } else {
            //获取分页数据
            Page<SearchPortraitVo> searchPage = this.findSearchPage(searchRequestVo.getPageParam(), new ArrayList<>(searchRequestVo.getFaceApiResultMap().keySet()), searchRequestVo.getLibIdList(), searchRequestVo.getFaceApiResultMap());
            searchResultVo.setResultPage(searchPage);
            searchResultVo.setFaceApiResultMap(searchRequestVo.getFaceApiResultMap());
            searchResultVo.setFaceImageRequestList(searchRequestVo.getFaceImageRequestList());
            //将部分请求参数返回前端，方便前端进行数据绑定
            searchResultVo.setRequestLibIdList(searchRequestVo.getLibIdList());
            if (UtilValidate.isNotEmpty(searchRequestVo.getPageParam().getNote().get("search"))) {
                searchResultVo.setRequestSearch(searchRequestVo.getPageParam().getNote().get("search").replaceAll("%", ""));
            }
            return searchResultVo;
        }
    }

    /**
     * 人脸检索分页
     *
     * @param pageParam
     * @param faceIdList       人脸Id集合
     * @param libraryIdList    库Id集合
     * @param faceApiResultMap 人脸分数集合
     * @return
     */
    private Page<SearchPortraitVo> findSearchPage(PageParam pageParam, List<String> faceIdList, List<String> libraryIdList, Map<String, Double> faceApiResultMap) {
        Page<SearchPortraitVo> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
        Map<String, String> searchParams = pageParam.paramsToLike(pageParam.getNote(), "search");
        /**
         *  查询出来的数据为乱序，即使对入参做了排序，也没有用，故此处的查询的唯一作用是用于判断有效的记录条数
         *  然后再根据当前页，以及当前页面的入参数据进行一次有效的查询,查询出来的结果依然为乱序，然后再根据、
         *  faceApiResultMap 与Id的对应关系再进行一次排序作为返回值
         */
        // 获取总的有效数量，
        Integer pageCount = baseMapper.findSearchPageCount(searchParams, faceIdList, libraryIdList);
        page.setTotal(pageCount);
        List<SearchPortraitVo> pageList;
        // 通过API调用
        if (UtilValidate.isNotEmpty(faceIdList) && UtilValidate.isNotEmpty(libraryIdList) && UtilValidate.isNotEmpty(faceApiResultMap)) {
            pageList = baseMapper.findSearchPageList(searchParams, this.getSubFaceIdList(faceIdList, page), libraryIdList);
            // 获取当前页有效数据
            // 设置人脸分数
            if (UtilValidate.isNotEmpty(faceApiResultMap)) {
                for (SearchPortraitVo searchPortraitVo : pageList) {
                    if (faceApiResultMap.containsKey(searchPortraitVo.getIdPortrait())) {
                        searchPortraitVo.setSimilarityDegree(faceApiResultMap.get(searchPortraitVo.getIdPortrait()));
                    }
                }
            }
            //对返回的数据进行排序
            Collections.sort(pageList);
            page.setRecords(pageList);
            return page;
        } else {
            // 非API调用
            pageList = baseMapper.findSearchPage(page, searchParams, null, libraryIdList);
            page.setRecords(pageList);
            return page;
        }

    }

    /**
     * 对返回的人脸结果集进行排序
     *
     * @param sortMap
     * @return
     */
    private Map<String, Double> sort(Map<String, Double> sortMap) {
        // 通过ArrayList构造函数把map.entrySet()转换成list
        List<Map.Entry<String, Double>> sortList = new ArrayList<>(sortMap.entrySet());
        Collections.sort(sortList, new Comparator<Map.Entry<String, Double>>() {
            @Override
            public int compare(Map.Entry<String, Double> o1, Map.Entry<String, Double> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });
        Map<String, Double> resultMap = new LinkedHashMap<>();
        Iterator<Map.Entry<String, Double>> iterator = sortList.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Double> next = iterator.next();
            resultMap.put(next.getKey(), next.getValue());
        }
        return resultMap;
    }

    /**
     * 截取人脸Id子集合
     *
     * @param faceIdList 需要剪裁的集合
     * @param page       page对象
     * @return
     */
    private List<String> getSubFaceIdList(List<String> faceIdList, Page page) {
        if (UtilValidate.isEmpty(faceIdList)) {
            return null;
        }
        // 每页数量
        long pageSize = page.getSize();
        // 当前页
        long current = page.getCurrent();
        // 总记录数量
        long total = page.getTotal();
        long start = (current - 1) * pageSize;
        long end = current * pageSize;
        if (end > total) {
            end = total;
        }
        if (start > end) {
            return null;
        }
        return faceIdList.subList(new Long(start).intValue(), new Long(end).intValue());
    }

    public static void main(String[] args) {
        String s = "513902199202293979";
        System.out.println(s.hashCode() % 500);
    }
}
